/*
* Copyright 2006 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.directwebremoting.spring;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.directwebremoting.create.NewCreator;
import org.directwebremoting.filter.ExtraLatencyAjaxFilter;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.HierarchicalBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.BeanDefinitionParserDelegate;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The Spring namespace handler which handles all elements that are defined as
* part of the DWR namespace, except <dwr:annotation-config />. <br/>
* The DWR namespace is defined in the <code>spring-dwr-X.X.xsd</code> file. All
* elements that are encountered in Spring configuration files are automatically
* converted to their actual bean representation in the Spring bean registry.
*
* @author Erik Wiersma
* @author Bram Smeets
* @author Jose Noheda
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public abstract class DwrNamespaceHandler extends NamespaceHandlerSupport
{
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init()
{
// register bean definition parsers and decorators for all dwr namespace elements
registerBeanDefinitionParser("configuration", new ConfigurationBeanDefinitionParser());
registerBeanDefinitionParser("controller", new ControllerBeanDefinitionParser());
registerBeanDefinitionParser("url-mapping", new UrlMappingBeanDefinitionParser());
registerBeanDefinitionParser("proxy-ref", new ProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("init", new InitDefinitionDecorator());
registerBeanDefinitionDecorator("create", new CreatorBeanDefinitionDecorator());
registerBeanDefinitionDecorator("convert", new ConverterBeanDefinitionDecorator());
registerBeanDefinitionDecorator("signatures", new SignaturesBeanDefinitionDecorator());
registerBeanDefinitionDecorator("remote", new RemoteBeanDefinitionDecorator());
}
protected static BeanDefinition registerSpringConfiguratorIfNecessary(BeanDefinitionRegistry registry)
{
if (!registry.containsBeanDefinition(DEFAULT_SPRING_CONFIGURATOR_ID))
{
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(SpringConfigurator.class);
builder.addPropertyValue("creators", new ManagedMap());
builder.addPropertyValue("converters", new ManagedMap());
registry.registerBeanDefinition(DEFAULT_SPRING_CONFIGURATOR_ID, builder.getBeanDefinition());
}
return registry.getBeanDefinition(DEFAULT_SPRING_CONFIGURATOR_ID);
}
/**
* Registers a new {@link org.directwebremoting.extend.Creator} in the registry using name <code>javascript</code>.
* @param registry The definition of all the Beans
* @param javascript The name of the bean in the registry.
* @param creatorConfig
* @param params
* @param children The node list to check for nested elements
*/
@SuppressWarnings("unchecked")
protected void registerCreator(BeanDefinitionRegistry registry, String javascript, BeanDefinitionBuilder creatorConfig, Map<String, String> params, NodeList children)
{
registerSpringConfiguratorIfNecessary(registry);
List<String> includes = new ArrayList<String>();
creatorConfig.addPropertyValue("includes", includes);
List<String> excludes = new ArrayList<String>();
creatorConfig.addPropertyValue("excludes", excludes);
Map<String, List<String>> auth = new HashMap<String, List<String>>();
creatorConfig.addPropertyValue("auth", auth);
// check to see if there are any nested elements here
for (int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) node;
if ("dwr:latencyfilter".equals(node.getNodeName()))
{
BeanDefinitionBuilder beanFilter = BeanDefinitionBuilder.rootBeanDefinition(ExtraLatencyAjaxFilter.class);
beanFilter.addPropertyValue("delay", child.getAttribute("delay"));
BeanDefinitionHolder holder2 = new BeanDefinitionHolder(beanFilter.getBeanDefinition(), "__latencyFilter_" + javascript);
BeanDefinitionReaderUtils.registerBeanDefinition(holder2, registry);
ManagedList filterList = new ManagedList();
filterList.add(new RuntimeBeanReference("__latencyFilter_" + javascript));
creatorConfig.addPropertyValue("filters", filterList);
}
else if ("dwr:include".equals(node.getNodeName()))
{
includes.add(child.getAttribute("method"));
}
else if ("dwr:exclude".equals(node.getNodeName()))
{
excludes.add(child.getAttribute("method"));
}
else if ("dwr:auth".equals(node.getNodeName()))
{
String method = child.getAttribute("method");
if (auth.get(method) == null)
{
auth.put(method, new ArrayList<String>());
}
auth.get(method).add(child.getAttribute("role"));
}
else if ("dwr:convert".equals(node.getNodeName()))
{
Element element = (Element) node;
String type = element.getAttribute("type");
String className = element.getAttribute("class");
ConverterConfig converterConfig = new ConverterConfig();
converterConfig.setType(type);
parseConverterSettings(converterConfig, element);
lookupConverters(registry).put(className, converterConfig);
}
else if ("dwr:filter".equals(node.getNodeName()))
{
Element element = (Element) node;
String filterClass = element.getAttribute("class");
List<Element> filterParamElements = DomUtils.getChildElementsByTagName(element, "param");
BeanDefinitionBuilder beanFilter;
try
{
beanFilter = BeanDefinitionBuilder.rootBeanDefinition(ClassUtils.forName(filterClass));
}
catch (ClassNotFoundException e)
{
throw new IllegalArgumentException("DWR filter class '" + filterClass + "' was not found. " + "Check the class name specified in <dwr:filter class=\"" + filterClass + "\" /> exists");
}
for (Element filterParamElement : filterParamElements)
{
beanFilter.addPropertyValue(filterParamElement.getAttribute("name"), filterParamElement.getAttribute("value"));
}
BeanDefinitionHolder holder2 = new BeanDefinitionHolder(beanFilter.getBeanDefinition(), "__filter_" + filterClass + "_" + javascript);
BeanDefinitionReaderUtils.registerBeanDefinition(holder2, registry);
ManagedList filterList = new ManagedList();
filterList.add(new RuntimeBeanReference("__filter_" + filterClass + "_" + javascript));
creatorConfig.addPropertyValue("filters", filterList);
}
else if ("dwr:param".equals(node.getNodeName()))
{
Element element = (Element) node;
String name = element.getAttribute("name");
String value = element.getAttribute("value");
params.put(name, value);
}
else
{
throw new RuntimeException("an unknown dwr:remote sub node was fouund: " + node.getNodeName());
}
}
creatorConfig.addPropertyValue("params", params);
String creatorConfigName = "__" + javascript;
BeanDefinitionHolder holder3 = new BeanDefinitionHolder(creatorConfig.getBeanDefinition(), creatorConfigName);
BeanDefinitionReaderUtils.registerBeanDefinition(holder3, registry);
lookupCreators(registry).put(javascript, new RuntimeBeanReference(creatorConfigName));
}
protected class ConfigurationBeanDefinitionParser implements BeanDefinitionParser
{
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
*/
@SuppressWarnings("unchecked")
public BeanDefinition parse(Element element, ParserContext parserContext)
{
BeanDefinitionRegistry registry = parserContext.getRegistry();
BeanDefinition beanDefinition = registerSpringConfiguratorIfNecessary(registry);
Element initElement = DomUtils.getChildElementByTagName(element, "init");
if (initElement != null)
{
decorate(initElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
List<Element> createElements = DomUtils.getChildElementsByTagName(element, "create");
for (Element createElement : createElements)
{
decorate(createElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
List<Element> convertElements = DomUtils.getChildElementsByTagName(element, "convert");
for (Element convertElement : convertElements)
{
decorate(convertElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
List<Element> signatureElements = DomUtils.getChildElementsByTagName(element, "signatures");
for (Element signatureElement : signatureElements)
{
decorate(signatureElement, new BeanDefinitionHolder(beanDefinition, DEFAULT_SPRING_CONFIGURATOR_ID), parserContext);
}
return beanDefinition;
}
}
protected static class ControllerBeanDefinitionParser implements BeanDefinitionParser
{
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
*/
@SuppressWarnings("unchecked")
public BeanDefinition parse(Element element, ParserContext parserContext)
{
BeanDefinitionBuilder dwrController = BeanDefinitionBuilder.rootBeanDefinition(DwrController.class);
List<Object> configurators = new ManagedList();
configurators.add(new RuntimeBeanReference(DEFAULT_SPRING_CONFIGURATOR_ID));
dwrController.addPropertyValue("configurators", configurators);
String debug = element.getAttribute("debug");
if (StringUtils.hasText(debug))
{
dwrController.addPropertyValue("debug", debug);
}
String beanName = element.getAttribute(BeanDefinitionParserDelegate.ID_ATTRIBUTE);
String nameAttr = element.getAttribute(BeanDefinitionParserDelegate.NAME_ATTRIBUTE);
String[] aliases = null;
if (!StringUtils.hasText(beanName))
{
beanName = element.getAttribute("name");
if (!StringUtils.hasText(beanName))
{
beanName ="dwrController"; // Offer a sensible default if no id was specified
}
}
else
{
String aliasName = element.getAttribute("name");
if (StringUtils.hasText(aliasName))
{
aliases = StringUtils.tokenizeToStringArray(nameAttr, BeanDefinitionParserDelegate.BEAN_NAME_DELIMITERS);
}
}
parseControllerParameters(dwrController, element);
BeanDefinitionHolder holder = new BeanDefinitionHolder(dwrController.getBeanDefinition(), beanName, aliases);
BeanDefinitionReaderUtils.registerBeanDefinition(holder, parserContext.getRegistry());
return dwrController.getBeanDefinition();
}
/**
* @param dwrControllerDefinition
* @param parent
*/
protected void parseControllerParameters(BeanDefinitionBuilder dwrControllerDefinition, Element parent)
{
NodeList children = parent.getChildNodes();
Map<String, String> params = new HashMap<String, String>();
for (int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) node;
if ("dwr:config-param".equals(child.getNodeName()))
{
String paramName = child.getAttribute("name");
String value = child.getAttribute("value");
params.put(paramName, value);
}
else
{
throw new RuntimeException("an unknown dwr:controller sub node was found: " + node.getNodeName());
}
}
dwrControllerDefinition.addPropertyValue("configParams", params);
}
}
/**
* Registers a new bean definition based on <dwr:url-mapping /> schema.
*
* @author Jose Noheda [jose.noheda@gmail.com]
*/
protected class UrlMappingBeanDefinitionParser implements BeanDefinitionParser
{
/**
* Converts <dwr:url-mapping /> tag in the adequate DwrHandlerMapping bean definition.
* @param element the <dwr:url-mapping /> tag
* @param parserContext access to the registry
* @return a DwrHandlerMapping bean definition
*/
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DwrHandlerMapping.class);
String interceptors = element.getAttribute("interceptors");
if (StringUtils.hasText(interceptors))
{
builder.addPropertyReference("interceptors", interceptors);
}
parserContext.getRegistry().registerBeanDefinition("DwrAnnotationURLMapper", builder.getBeanDefinition());
return parserContext.getRegistry().getBeanDefinition("DwrAnnotationURLMapper");
}
}
/**
* Registers a bean proxy based in <dwr:proxy-ref />
*
* @author Jose Noheda [jose.noheda@gmail.com]
*/
protected class ProxyBeanDefinitionParser implements BeanDefinitionParser
{
public BeanDefinition parse(Element element, ParserContext parserContext)
{
String beanRef = element.getAttribute("bean");
BeanDefinitionRegistry registry = parserContext.getRegistry();
BeanDefinition beanRefDefinition = findParentDefinition(beanRef, registry);
//BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanRefDefinition, beanRef);
String javascript = element.getAttribute("javascript");
if (!StringUtils.hasText(javascript))
{
if (log.isDebugEnabled())
{
log.debug("No javascript name provided. Remoting using bean id [" + beanRef + "]");
}
javascript = StringUtils.capitalize(beanRef);
}
BeanDefinitionBuilder beanCreator = BeanDefinitionBuilder.rootBeanDefinition(BeanCreator.class);
beanCreator.addPropertyValue("beanClass", resolveBeanClassname(beanRefDefinition, registry));
beanCreator.addPropertyValue("beanId", beanRef);
beanCreator.addDependsOn(beanRef);
beanCreator.addPropertyValue("javascript", javascript);
BeanDefinitionBuilder creatorConfig = BeanDefinitionBuilder.rootBeanDefinition(CreatorConfig.class);
creatorConfig.addPropertyValue("creator", beanCreator.getBeanDefinition());
registerCreator(parserContext.getRegistry(), javascript, creatorConfig, new HashMap<String, String>(), element.getChildNodes());
return creatorConfig.getBeanDefinition();
}
}
protected class RemoteBeanDefinitionDecorator implements BeanDefinitionDecorator
{
/**
* Registers an <dwr:remote ... /> element.
*/
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
Element element = (Element) node;
String javascript = element.getAttribute("javascript");
BeanDefinitionBuilder beanCreator = BeanDefinitionBuilder.rootBeanDefinition(BeanCreator.class);
try
{
String beanClassName = resolveBeanClassname(definition.getBeanDefinition(), parserContext.getRegistry());
if (beanClassName == null)
{
throw new FatalBeanException("Unabled to find type for beanName '" + definition.getBeanName() + "'. " + "Check your bean has a correctly configured parent or provide a class for " + " the bean definition");
}
beanCreator.addPropertyValue("beanClass", ClassUtils.forName(beanClassName));
}
catch (ClassNotFoundException e)
{
throw new FatalBeanException("Unable to create DWR bean creator for '" + definition.getBeanName() + "'.", e);
}
String name = definition.getBeanName();
if (name.startsWith("scopedTarget."))
{
name = name.substring(name.indexOf(".") + 1);
}
beanCreator.addPropertyValue("beanId", name);
if (!StringUtils.hasText(javascript))
{
if (log.isDebugEnabled())
{
log.debug("No javascript name provided. Remoting using bean id [" + name + "]");
}
javascript = StringUtils.capitalize(name);
}
beanCreator.addPropertyValue("javascript", javascript);
BeanDefinitionBuilder creatorConfig = BeanDefinitionBuilder.rootBeanDefinition(CreatorConfig.class);
creatorConfig.addPropertyValue("creator", beanCreator.getBeanDefinition());
registerCreator(parserContext.getRegistry(), javascript, creatorConfig, new HashMap<String, String>(), node.getChildNodes());
return definition;
}
}
/**
* Try getting the beanClassName from the definition and if that fails try to get it from
* the parent (and even parent BeanFactory if we have to).
* @param definition
* @param registry
* @return class name or null if not found
*/
protected static String resolveBeanClassname(BeanDefinition definition, BeanDefinitionRegistry registry)
{
String beanClassName = definition.getBeanClassName();
while(!StringUtils.hasText(beanClassName))
{
try
{
Method m = definition.getClass().getMethod("getParentName", new Class[0]);
String parentName = (String) m.invoke(definition, new Object[0]);
BeanDefinition parentDefinition = findParentDefinition(parentName, registry);
beanClassName = parentDefinition.getBeanClassName();
definition = parentDefinition;
} catch (Exception e)
{
throw new FatalBeanException("No parent bean could be found for " + definition, e);
}
}
return beanClassName;
}
protected static BeanDefinition findParentDefinition(String parentName, BeanDefinitionRegistry registry)
{
if (registry != null)
{
if (registry.containsBeanDefinition(parentName))
{
return registry.getBeanDefinition(parentName);
}
else if (registry instanceof HierarchicalBeanFactory)
{
// Try to get parent definition from the parent BeanFactory. This could return null
BeanFactory parentBeanFactory = ((HierarchicalBeanFactory) registry).getParentBeanFactory();
return findParentDefinition(parentName, (BeanDefinitionRegistry) parentBeanFactory);
}
}
// we've exhausted all possibilities
return null;
}
protected class ConverterBeanDefinitionDecorator implements BeanDefinitionDecorator
{
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
Element element = (Element) node;
String type = element.getAttribute("type");
if ("preconfigured".equals(type))
{
type += ":" + element.getAttribute("ref");
}
String className = element.getAttribute("class");
String javascriptClassName = element.getAttribute("javascript");
BeanDefinitionRegistry registry = parserContext.getRegistry();
ConverterConfig converterConfig = new ConverterConfig();
converterConfig.setType(type);
converterConfig.setJavascriptClassName(javascriptClassName);
parseConverterSettings(converterConfig, element);
lookupConverters(registry).put(className, converterConfig);
return definition;
}
}
/**
* @param converterConfig
* @param parent
*/
protected void parseConverterSettings(ConverterConfig converterConfig, Element parent)
{
NodeList children = parent.getChildNodes();
// check to see if there are any nested elements here
for (int i = 0; i < children.getLength(); i++)
{
Node node = children.item(i);
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) node;
if ("dwr:include".equals(child.getNodeName()))
{
converterConfig.addInclude(child.getAttribute("method"));
}
else if ("dwr:exclude".equals(child.getNodeName()))
{
converterConfig.addExclude(child.getAttribute("method"));
}
/* TODO Why is this only a property of ObjectConverter?
else if (child.getNodeName().equals("dwr:force"))
{
converterConfig.setForce(Boolean.parseBoolean(child.getAttribute("value")));
}
*/
else
{
throw new RuntimeException("an unknown dwr:remote sub node was found: " + node.getNodeName());
}
}
}
/**
* Parse the <code><dwr:init></code> elements
*/
protected class InitDefinitionDecorator implements BeanDefinitionDecorator
{
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.BeanDefinitionDecorator#decorate(org.w3c.dom.Node, org.springframework.beans.factory.config.BeanDefinitionHolder, org.springframework.beans.factory.xml.ParserContext)
*/
public BeanDefinitionHolder decorate(Node parent, BeanDefinitionHolder definition, ParserContext parserContext)
{
Map<String, String> converters = new HashMap<String, String>();
Map<String, String> creators = new HashMap<String, String>();
NodeList inits = parent.getChildNodes();
for (int j = 0; j < inits.getLength(); j++)
{
Node node = inits.item(j);
if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) inits.item(j);
if (child.getNodeName().equals(ELEMENT_CREATOR))
{
String id = child.getAttribute(ATTRIBUTE_ID);
String className = child.getAttribute(ATTRIBUTE_CLASS);
creators.put(id, className);
}
else if (child.getNodeName().equals(ELEMENT_CONVERTER))
{
String id = child.getAttribute(ATTRIBUTE_ID);
String className = child.getAttribute(ATTRIBUTE_CLASS);
converters.put(id, className);
}
else
{
throw new RuntimeException("An unknown sub node '" + child.getNodeName() + "' was found while parsing dwr:init");
}
}
BeanDefinition configurator = registerSpringConfiguratorIfNecessary(parserContext.getRegistry());
configurator.getPropertyValues().addPropertyValue("creatorTypes", creators);
configurator.getPropertyValues().addPropertyValue("converterTypes", converters);
return definition;
}
}
/**
* Uses the BeanDefinitionDecorator since we need access to the name of the parent definition??
* Register the creatores: spring, new, null, scripted, jsf, struts, pageflow
*/
protected class CreatorBeanDefinitionDecorator implements BeanDefinitionDecorator
{
/* (non-Javadoc)
* @see org.springframework.beans.factory.xml.BeanDefinitionDecorator#decorate(org.w3c.dom.Node, org.springframework.beans.factory.config.BeanDefinitionHolder, org.springframework.beans.factory.xml.ParserContext)
*/
@SuppressWarnings("unchecked")
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
Element element = (Element) node;
String javascript = element.getAttribute("javascript");
String creatorType = element.getAttribute("type");
BeanDefinitionBuilder creatorConfig = BeanDefinitionBuilder.rootBeanDefinition(CreatorConfig.class);
// Configure "known" creators in the CreatorConfig. If unknown then just create the configuration
// and leave it up DWR itself to decide if it's a valid creator type
BeanDefinitionBuilder creator;
Map<String, String> params = new HashMap<String, String>();
if ("spring".equals(creatorType))
{
// TODO Refactor so that both spring creators use the same code...
BeanDefinitionBuilder springCreator = BeanDefinitionBuilder.rootBeanDefinition(BeanCreator.class);
springCreator.addPropertyValue("javascript", javascript);
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
Node childNode = children.item(i);
if (childNode.getNodeType() == Node.TEXT_NODE || childNode.getNodeType() == Node.COMMENT_NODE)
{
continue;
}
Element child = (Element) childNode;
String paramName = child.getAttribute("name");
String value = child.getAttribute("value");
if ("beanName".equals(paramName) || "beanId".equals(paramName)) {
springCreator.addPropertyValue("beanId", value);
} else {
params.put(paramName, value);
}
}
creatorConfig.addPropertyValue("creator", springCreator.getBeanDefinition());
}
else if ("new".equals(creatorType))
{
creator = BeanDefinitionBuilder.rootBeanDefinition(NewCreator.class);
creator.addPropertyValue("className", node.getAttributes().getNamedItem("class").getNodeValue());
creator.addPropertyValue("javascript", javascript);
creatorConfig.addPropertyValue("creator", creator.getBeanDefinition());
}
else if ("null".equals(creatorType))
{
creatorConfig.addPropertyValue("creatorType", "none");
String className = element.getAttribute("class");
if (className == null || "".equals(className))
{
throw new BeanInitializationException("'class' is a required attribute for the declaration <dwr:creator type=\"null\"" + " javascript=\"" + javascript + "\" ... />");
}
params.put("class", className);
}
else if ("pageflow".equals(creatorType))
{
creatorConfig.addPropertyValue("creatorType", creatorType);
}
else if ("jsf".equals(creatorType) || "scripted".equals(creatorType) || "struts".equals(creatorType))
{
creatorConfig.addPropertyValue("creatorType", creatorType);
}
else
{
if (log.isDebugEnabled())
{
log.debug("Looking up creator type '" + creatorType + "'");
}
// TODO We should delay the initialization of the creatorClass until after the bean
// definitions have been parsed.
BeanDefinition configurator = registerSpringConfiguratorIfNecessary(parserContext.getRegistry());
PropertyValue registeredCreators = configurator.getPropertyValues().getPropertyValue("creatorTypes");
Map<String, String> registeredCreatorMap = (Map<String, String>) registeredCreators.getValue();
String creatorClass = registeredCreatorMap.get(creatorType);
if (creatorClass == null)
{
// the creator type should have been registered
throw new UnsupportedOperationException("Type " + creatorType + " is not supported " + " or the custom creator has not been registered dwr:init");
}
else
{
try
{
Class<?> clazz = Class.forName(creatorClass);
creator = BeanDefinitionBuilder.rootBeanDefinition(clazz);
creatorConfig.addPropertyValue("creator", creator.getBeanDefinition());
String className = element.getAttribute("class");
if (StringUtils.hasText(className))
{
params.put("class", className);
}
}
catch (ClassNotFoundException ex)
{
throw new FatalBeanException("ClassNotFoundException trying to register " + " creator '" + creatorClass + "' for javascript type '" + javascript + "'. Check the "
+ " class in the classpath and that the creator is register in dwr:init", ex);
}
}
}
registerCreator(parserContext.getRegistry(), javascript, creatorConfig, params, node.getChildNodes());
return definition;
}
}
protected class SignaturesBeanDefinitionDecorator implements BeanDefinitionDecorator
{
public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext)
{
BeanDefinitionRegistry registry = parserContext.getRegistry();
BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);
StringBuffer sigtext = new StringBuffer();
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++)
{
Node child = children.item(i);
if (child.getNodeType() != Node.TEXT_NODE && child.getNodeType() != Node.CDATA_SECTION_NODE)
{
log.warn("Ignoring illegal node type: " + child.getNodeType());
continue;
}
sigtext.append(child.getNodeValue());
}
config.getPropertyValues().addPropertyValue("signatures", sigtext.toString());
return definition;
}
}
/**
* @param registry
* @return Get a list of the defined Creators
*/
@SuppressWarnings("unchecked")
protected static Map<String, RuntimeBeanReference> lookupCreators(BeanDefinitionRegistry registry)
{
BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);
return (Map<String, RuntimeBeanReference>) config.getPropertyValues().getPropertyValue("creators").getValue();
}
/**
* @param registry
* @return Get a list of the defined Converters
*/
@SuppressWarnings("unchecked")
protected static Map<String, ConverterConfig> lookupConverters(BeanDefinitionRegistry registry)
{
BeanDefinition config = registerSpringConfiguratorIfNecessary(registry);
return (Map<String, ConverterConfig>) config.getPropertyValues().getPropertyValue("converters").getValue();
}
protected static final String DEFAULT_SPRING_CONFIGURATOR_ID = "__dwrConfiguration";
/**
* The log stream
*/
private static final Log log = LogFactory.getLog(DwrNamespaceHandler.class);
/*
* The element names
*/
private static final String ELEMENT_CONVERTER = "dwr:converter";
private static final String ELEMENT_CREATOR = "dwr:creator";
/*
* The attribute names
*/
private static final String ATTRIBUTE_ID = "id";
private static final String ATTRIBUTE_CLASS = "class";
}